package com.third.device.mg.serialport.factory.haobo.product

import com.third.device.mg.serialport.factory.haobo.BaseHaoBoProduct
import com.third.device.mg.serialport.utils.toZeroString

/**
 * @Date 2022/6/10
 * Description:RS232 转 红外
 * https://item.taobao.com/item.htm?spm=a230r.1.14.16.6fec53e09kfNwB&id=604041020710&ns=1&abbucket=3#detail
 */
class RS232TInfrared : BaseHaoBoProduct() {

    override fun productDescribe(): String = "浩博智控商城--存储型--红外控制器--可存500 个按键编码"

    /**
     * 1:
     * 获取学习指令 -- 指令
     * 发送：RIR
     * 接收：学习成功，返回 RIRxxx；学习超时返回 TIMEOUT
     * xxx 是 001-499，表示从 1 到 500 个序号，总共 500 个；
     */
    fun getLearn(): ByteArray {
        return "RIR".toByteArray()
    }

    /**
     * 2:
     * 发送红外遥控按键编码（只需发送一个序号） -- 指令
     * 发送：SIRxxx，xxx 是学习到的相应的序号
     * 返回：发送成功，返回 SOK
     * @param number [1,500]
     */
    fun getSend(number: Int): ByteArray {
        return if (number in 1..500) {
            val command = "SIR${number.toZeroString(3)}"
            command.toByteArray()
        } else {
            "SIR001".toByteArray()
        }
    }

    /**
     * 3:
     * 查询最近学习过的遥控按键的序号 -- 指令
     * 发送：CIR
     * 返回：IDxxx，xxx 是最近存储的学习到的红外按键的序号；
     * 此命令返回的编号，是命令 1 的学习成功后的最后编号，不代表内存中已有的编号个
     * 数，因为可以通过命令 8 进行红外数据的写入固化操作，以及命令 4 进行编号数据的
     * 的重新学习
     */
    fun getQueryNumber(): ByteArray {
        return "CIR".toByteArray()
    }

    /**
     * 4:
     * 覆盖已学习过遥控按键 -- 指令
     * 发送：RIRxxx，xxx 是需要重新学习的红外序号，注意 xxx 需要 s 是已通过 RIR 学习
     * 过的编号（本命令用来覆盖之前学习过的编号，未学习过的使用此命令也有效，也可
     * 使用 SIRxxx 命令发送对应编号）
     * 返回：请参考 RIR 的返回
     * @param number [1,500]
     */
    fun getResetLearn(number: Int): ByteArray {
        return if (number in 1..500) {
            val command = "RIR${number.toZeroString(3)}"
            command.toByteArray()
        } else {
            "RIR001".toByteArray()
        }
    }

    /**
     * 5:
     * 存储序号复位 -- 指令(清除所有按键数据)
     * 发送：ERM
     * 返回：EOK，擦除存储的所有数据，学习红外按键的序号将从零开始
     */
    fun getClearNumber(): ByteArray {
        return "ERM".toByteArray()
    }


    /**
     * 6:
     * 修改波特率 -- 指令
     * 发送：CHBDx，其中 x 是 1-5，分别是 4800、9600、19200、38400 和 115200 五种波特
     * 率，例如 CHBD2 是设置 9600，CHBD5 是设置 115200；并且，此修改的波特率能断电保
     * 存配置。
     * 返回：成功则返回 Set Baud OK ,system will reset after 2 seconds
     * 修改成功后，模块会 2 秒后自动重启，重启后会按照新设置的波特率进行通信；
     * 若忘记使用所设置的波特率，只能上电返回版本数据或者发送其他命令例如命令 3 或
     * 5 之类的来查询验证。
     *
     * @param level [1,5]
     * 1 :4800Bps
     * 2 :9600Bps
     * 3 :19200Bps
     * 4 :38400Bps
     * 5 :115200Bps
     * 默认是9600Bps
     */
    fun getSetBps(level: Int = 2): ByteArray {
        return if (level in 1..5) {
            val command = "CHBD$level"
            command.toByteArray()
        } else {
            "CHBD2".toByteArray()
        }
    }

    /**
     * 7:
     * 读取学习过的红外按键编码数据 -- 指令
     * 发送：RDMxxx，其中 xxx 是从 001-500 组编号，分别是命令 1 和命令 4 中的学习过的
     * 500 组编号的红外按键数据，此数据可通过命令 8 写入模块的任意一组编号中（可以
     * 写入本模块也可写入其他模块），学习过和未学习过的编号使用此命令也有效，也可
     * 使用 SIRxxx 命令发送对应编号。
     * 返回：若之前学习过或者写入过此编号的红外数据，则成功返回以字符“RMI”开头的
     * 一串数据；否则返回 Flash data Err；正确返回的数据，需要以十六进制来接收和查
     * 看，例如收到的数据是：
     * 52 4D 49 88 00 62 0D A1 06 C5 00 EB 00 C3 00 EB 00 C5 00 EB 00 C3 00 EE 00
     * C3 00 EB 00 C5 00 EB 00 C3 00 EB 00 C3 00 EB 00 C5 00 80 02 C5 00 80 02 C5
     * 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C3 00
     * EB 00 C5 00 EB 00 C5 00 80 02 CF 00 82 02 BB 00 80 02 C5 00 EB 00 C5 00 EB
     * 00 CA 00 E4 00 C3 00 82 02 C3 00 80 02 C5 00 EB 00 C5 00 EB 00 C3 00 EB 00
     * C5 00 80 02 C5 00 80 02 C5 00 80 02 C3 00 D5 30 00 00 33 12
     * 对此数据的结构和分析如下：52 4D 49 这三个字节的就是 ‘R’‘M’‘I’三个字符
     * 的十六进制形式，88 00 是有效的红外数据个数，十六进制格式，0x88=136,个数是
     * 256*0+136=136 个有效红外字节，后面跟着的是 136 个字节的有效红外数据，最后四
     * 个字节 00 00 33 12，是从第三个字节 0x49 开始到最后一个有效红外数据 0x30 的和
     * 0x00003312;有效的红外数据，由于存在一定的技术复杂度，属于比较深奥的内容，专
     * 业性很强，因此，有兴趣研究的用户请自行分析，不提供详细的技术分析。
     *
     * @param number [1,500]
     */
    fun getReadData(number: Int): ByteArray {
        return if (number in 1..500) {
            val command = "RDM${number.toZeroString(3)}"
            command.toByteArray()
        } else {
            "RDM001".toByteArray()
        }
    }


    /**
     * 8:
     * 将数据写入到设备里面
     * 写入红外编码数据到板载内存
     * 发送：WIDxxx 红外按键编码数据
     * 其中，xxx 是需要写入的编码编号，此编号从 1-500，其意义和以上命令一致，后面跟
     * 的红外数据的格式必须按照命令 7 中学习到的数据格式，内容一般也不做修改，如果
     * 需要修改则必须把 7 中学到的数据内容完成理解和掌握后再修改使用，对红外内容不
     * 做太多解释，用户自行研究即可。例如需要把命令 7 中举例的数据写入到编号是 150
     * 的内存中，则发送的数据命令如下：
     * 57 49 44 31 35 30 52 4D 49 88 00 62 0D A1 06 C5 00 EB 00 C3 00 EB 00 C5 00 EB
     * 00 C3 00 EE 00 C3 00 EB 00 C5 00 EB 00 C3 00 EB 00 C3 00 EB 00 C5 00 80 02 C5
     * 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80
     * 02 C3 00 EB 00 C5 00 EB 00 C5 00 80 02 CF 00 82 02 BB 00 80 02 C5 00 EB 00 C5
     * 00 EB 00 CA 00 E4 00 C3 00 82 02 C3 00 80 02 C5 00 EB 00 C5 00 EB 00 C3 00 EB
     * 00 C5 00 80 02 C5 00 80 02 C5 00 80 02 C3 00 D5 30 00 00 33 12
     * 其中，52 4D 49 88 00 62 0D A1 06 C5 00 EB 00 C3 00 EB 00 C5 00 EB 00 C3 00 EE
     * 00 C3 00 EB 00 C5 00 EB 00 C3 00 EB 00 C3 00 EB 00 C5 00 80 02 C5 00 80 02 C5
     * 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C5 00 80 02 C3 00 EB
     * 00 C5 00 EB 00 C5 00 80 02 CF 00 82 02 BB 00 80 02 C5 00 EB 00 C5 00 EB 00 CA
     * 00 E4 00 C3 00 82 02 C3 00 80 02 C5 00 EB 00 C5 00 EB 00 C3 00 EB 00 C5 00 80
     * 02 C5 00 80 02 C5 00 80 02 C3 00 D5 30 00 00 33 12 是 7 中举例读取到的学习过的
     * 编号的红外按键的数据，57 49 44 31 35 30 就是字符 WID150 的十六进制格式。
     * 返回：成功则返回 WIDOK
     * @param number [1,500] 新的按键序号
     * @param wData  写入的数据
     */
    fun getWriteData(number: Int, wData: ByteArray): ByteArray {
        val targetNumber = if (number in 1..500) {
            number
        } else {
            1
        }
        val target = "WID${targetNumber.toZeroString(3)}".toByteArray()
        return target.plus(wData)
    }


    /**
     * 9:(相当于设备恢复 出厂设定)
     * 擦除板载内存所有红外数据
     * 发送：ERMA
     * 此命令会擦除板子存储器的所有红外内存数据，擦除一次时间需要 15 秒以上，请小
     * 心使用，尽量少使用此命令，能不使用就不使用。
     * 返回，返回 ERMAOk
     */
    fun getResetDevice() :ByteArray{
        return "ERMA".toByteArray()
    }
}